package upms.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;

import java.util.Set;

import static java.util.Arrays.asList;

@Configuration(proxyBeanMethods = false)
class WebSecurityConfig {
    @Value("${permitUrls.${spring.application.name:}:}")
    Set<String> permitUrls;

    /**
     * @see OAuth2ResourceServerAutoConfiguration
     */
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        permitUrls.addAll(asList("/webjars/**", "/v3/api-docs", "/actuator/**", "/druid/**", "/error"));
        http.authorizeHttpRequests(requests -> requests
            .antMatchers(permitUrls.toArray(new String[0])).permitAll()
            .anyRequest().authenticated()
        ).oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())));
        return http.build();
    }

    @Bean
    WebSecurityCustomizer webSecurityCustomizer() {
        String[] IGNORING_URL = new String[]{"/favicon.ico", "/swagger-ui.html", "/webjars/**", "/v3/api-docs/**"};
        return web -> web.ignoring().antMatchers(IGNORING_URL);
    }

    JwtAuthenticationConverter jwtAuthenticationConverter() { // 解析 jwt token 中的权限信息
        // https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-authorization-extraction
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
        grantedAuthoritiesConverter.setAuthorityPrefix("");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }
}